#include "mydefines.hpp"
#include "autofree.h"
#include "minizip.h"
#include "zip.h"
#include <QDebug>
#include <iostream>

bool IsFileExist(const QString& path)
{
    QFile f;
    if (f.exists(path))
        return true;
    return false;
}


bool dlputils::MyZip(const QString &_zipname, const QStringList &_filenames, const QString &_password)
{
    assert(!_zipname.isEmpty());
    assert(_filenames.size() != 0);
    for (const QString& filename: _filenames) {
        if (!IsFileExist(filename)) {
            EST_LOG_ERROR("%s is not exist!", QTC(filename));
            return false;
        }
    }

    int opt_overwrite = 0;	//0 is overwrite
    int opt_compress_level = Z_DEFAULT_COMPRESSION;
    g_autofree const char *filename_try = strdup(QTC(_zipname));
//    char *filename_try = QTC(_zipname);
    int err = 0;

    int size_buf = WRITEBUFFERSIZE;
    g_autofree void *buf = (void *)malloc(size_buf);
    if (buf == NULL)
    {
        EST_LOG_ERROR("Error allocating memory\n");	//ZIP_INTERNALERROR
        return false;
    }

    int errclose;
    zipFile zf = zipOpen64(filename_try, (opt_overwrite == 2) ? 2 : 0);
    if (zf == NULL) {
        EST_LOG_ERROR("error opening %s\n", filename_try);
        return false;
    }

    for (const QString& filename: _filenames) {
        int size_read;
        unsigned long crcFile = 0;
        g_autofree const char *filenameinzip = strdup(QTC(filename));

        int zip64 = 0;

        zip_fileinfo zi;

        zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
                        zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
        zi.dosDate = 0;
        zi.internal_fa = 0;
        zi.external_fa = 0;
        filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);

        if (!_password.isEmpty())
            err = getFileCrc(filenameinzip, buf, size_buf, &crcFile);

        zip64 = isLargeFile(filenameinzip);

        /* The path name saved, should not include a leading slash. */
        /*if it did, windows/xp and dynazip couldn't read the zip file. */
        const char *savefilenameinzip = filenameinzip;
        while (savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/')
        {
            savefilenameinzip++;
        }

        err = zipOpenNewFileInZip3_64(zf, savefilenameinzip, &zi,
                                      NULL, 0, NULL, 0, NULL /* comment*/,
                                      (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                      opt_compress_level, 0,
                                      /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                                      -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                      _password.isEmpty() ? NULL : QTC(_password), crcFile, zip64);

        if (err != ZIP_OK) {
            EST_LOG_ERROR("error in opening %s in zipfile\n", filenameinzip);
            return false;
        }

        FILE *fin = fopen64(filenameinzip, "rb");
        if (fin == NULL)
        {
            EST_LOG_ERROR("error in opening %s for reading\n", filenameinzip);
            fclose(fin);
            return false;
        }

        do {
            err = ZIP_OK;
            size_read = (int)fread(buf, 1, size_buf, fin);
            if (size_read < size_buf)
                if (feof(fin) == 0)
                {
                    EST_LOG_ERROR("error in reading %s\n", filenameinzip);
                    err = ZIP_ERRNO;
                }

            if (size_read > 0)
            {
                err = zipWriteInFileInZip(zf, buf, size_read);
                if (err < 0)
                {
                    EST_LOG_ERROR("error in writing %s in the zipfile\n",
                           filenameinzip);
                }
            }
        } while ((err == ZIP_OK) && (size_read > 0));

        if (fin)
            fclose(fin);

        if (err < 0)
            err = ZIP_ERRNO;
        else
        {
            err = zipCloseFileInZip(zf);
            if (err != ZIP_OK)
                EST_LOG_ERROR("error in closing %s in the zipfile\n",
                       filenameinzip);
        }
    }

    errclose = zipClose(zf, NULL);
    if (errclose != ZIP_OK)
    {
        EST_LOG_ERROR("error in closing %s\n", filename_try);
    }

    return true;

}
